/*
* ParticleReader.cpp
*
*  Created on: 2009/03/04
*      Author: Yongshik Cho
*/

#include "ParticleReader.h"
#include "RenderableReader.h"
#include "../ParticleManager.h"
#include "../TextureManager.h"


const std::string ParticleReader::_PARTICLE_TYPE_TAG			= "ParticleType";
const std::string ParticleReader::_TOTAL_PARTICLE_TAG			= "TotalParticle";
const std::string ParticleReader::_DURATION_TAG					= "Duration";
const std::string ParticleReader::_GRAVITY_TAG					= "Gravity";
const std::string ParticleReader::_SOURCE_TAG					= "Source";
const std::string ParticleReader::_ANGLE_TAG					= "Angle";
const std::string ParticleReader::_ANGLE_VARIANCE_TAG			= "AngleVariance";
const std::string ParticleReader::_RADIAL_ACCEL_TAG				= "RadialAccel";
const std::string ParticleReader::_RADIAL_ACCEL_VARIANCE_TAG	= "RadialAccelVariance";
const std::string ParticleReader::_SPEED_TAG					= "Speed";
const std::string ParticleReader::_SPEED_VARIANCE_TAG			= "SpeedVariance";
const std::string ParticleReader::_POSITION_VARIANCE_TAG		= "PositionVariance";
const std::string ParticleReader::_LIFE_TAG						= "Life";
const std::string ParticleReader::_LIFE_VARIANCE_TAG			= "LifeVariance";
const std::string ParticleReader::_EMISSION_RATE_TAG			= "EmissionRate";
const std::string ParticleReader::_START_COLOLR_TAG				= "StartColor";
const std::string ParticleReader::_START_COLOR_VARIANCE_TAG		= "StartColorVariance";
const std::string ParticleReader::_END_COLOR_TAG				= "EndColor";
const std::string ParticleReader::_END_COLOR_VARIANCE_TAG		= "EndColorVariance";
const std::string ParticleReader::_SIZE_TAG						= "Size";
const std::string ParticleReader::_SIZE_VARIANCE_TAG			= "SizeVariance";
const std::string ParticleReader::_TEXTURE_TAG					= "Texture";
const std::string ParticleReader::_BLEND_ADDITIVE_TAG			= "BlendAdditive";
const std::string ParticleReader::_COLOR_MODULATE_TAG			= "ColorModulate";

const std::string ParticleReader::_PARTICLE_CUSTOM_TAG			= "CUSTOM";
const std::string ParticleReader::_PARTICLE_FIREWORKS_TAG		= "FIREWORKS";
const std::string ParticleReader::_PARTICLE_FIRE_TAG			= "FIRE";
const std::string ParticleReader::_PARTICLE_SUN_TAG				= "SUN";
const std::string ParticleReader::_PARTICLE_GALAXY_TAG			= "GALAXY";
const std::string ParticleReader::_PARTICLE_FLOWER_TAG			= "FLOWER";
const std::string ParticleReader::_PARTICLE_METEOR_TAG			= "METEOR";
const std::string ParticleReader::_PARTICLE_SPIRAL_TAG			= "SPIRAL";
const std::string ParticleReader::_PARTICLE_EXPLOSION_TAG		= "EXPLOSION";
const std::string ParticleReader::_PARTICLE_SMOKE_TAG			= "SMOKE";
const std::string ParticleReader::_PARTICLE_SNOW_TAG			= "SNOW";
const std::string ParticleReader::_PARTICLE_RAIN_TAG			= "RAIN";


ParticleObject* ParticleReader::parse(TiXmlElement* element)
{
	char* sParticleType = (char*)element->Attribute(_PARTICLE_TYPE_TAG.c_str());
	TiXmlElement* node = element->FirstChildElement(_PARTICLE_TYPE_TAG.c_str()); if(node) sParticleType = (char*)node->GetText();

	ParticleObject* particle = 0;
	if(sParticleType)
	{
		ParticleManager* pm = ParticleManager::GetInstancePtr();
		assert(pm);

		if(sParticleType == _PARTICLE_CUSTOM_TAG)
			particle = new ParticleObject();
		else if(sParticleType == _PARTICLE_FIREWORKS_TAG)
			particle = pm->createParticle(ParticleManager::PARTICLE_FIREWORKS);
		else if(sParticleType == _PARTICLE_FIRE_TAG)
			particle = pm->createParticle(ParticleManager::PARTICLE_FIRE);
		else if(sParticleType == _PARTICLE_SUN_TAG)
			particle = pm->createParticle(ParticleManager::PARTICLE_SUN);
		else if(sParticleType == _PARTICLE_GALAXY_TAG)
			particle = pm->createParticle(ParticleManager::PARTICLE_GALAXY);
		else if(sParticleType == _PARTICLE_FLOWER_TAG)
			particle = pm->createParticle(ParticleManager::PARTICLE_FLOWER);
		else if(sParticleType == _PARTICLE_METEOR_TAG)
			particle = pm->createParticle(ParticleManager::PARTICLE_METEOR);
		else if(sParticleType == _PARTICLE_SPIRAL_TAG)
			particle = pm->createParticle(ParticleManager::PARTICLE_SPIRAL);
		else if(sParticleType == _PARTICLE_EXPLOSION_TAG)
			particle = pm->createParticle(ParticleManager::PARTICLE_EXPLOSION);
		else if(sParticleType == _PARTICLE_SMOKE_TAG)
			particle = pm->createParticle(ParticleManager::PARTICLE_SMOKE);
		else if(sParticleType == _PARTICLE_SNOW_TAG)
			particle = pm->createParticle(ParticleManager::PARTICLE_SNOW);
		else if(sParticleType == _PARTICLE_RAIN_TAG)
			particle = pm->createParticle(ParticleManager::PARTICLE_RAIN);
	}

	if(!particle)
		return 0;

	RenderableReader::parseRenderable(element, particle);

	int32 tparticle = 0;
	double duration = 0.0, angle = 0.0, anglev = 0.0, radacc = 0.0, radaccv = 0.0, speed = 0.0, speedv = 0.0;
	double life = 0.0, lifev = 0.0, emissrate = 0.0, size = 0.0, sizev = 0.0;

	char* sTparticle = (char*)element->Attribute(_TOTAL_PARTICLE_TAG.c_str(), &tparticle);
	char* sDuration = (char*)element->Attribute(_DURATION_TAG.c_str(), &duration);
	char* sAngle = (char*)element->Attribute(_ANGLE_TAG.c_str(), &angle);
	char* sAnglev = (char*)element->Attribute(_ANGLE_VARIANCE_TAG.c_str(), &anglev);
	char* sRadacc = (char*)element->Attribute(_RADIAL_ACCEL_TAG.c_str(), &radacc);
	char* sRadaccv = (char*)element->Attribute(_RADIAL_ACCEL_VARIANCE_TAG.c_str(), &radaccv);
	char* sSpeed = (char*)element->Attribute(_SPEED_TAG.c_str(), &speed);
	char* sSpeedv = (char*)element->Attribute(_SPEED_VARIANCE_TAG.c_str(), &speedv);
	char* sLife = (char*)element->Attribute(_LIFE_TAG.c_str(), &life);
	char* sLifev = (char*)element->Attribute(_LIFE_VARIANCE_TAG.c_str(), &lifev);
	char* sEmissrate = (char*)element->Attribute(_EMISSION_RATE_TAG.c_str(), &emissrate);
	char* sSize = (char*)element->Attribute(_SIZE_TAG.c_str(), &size);
	char* sSizev = (char*)element->Attribute(_SIZE_VARIANCE_TAG.c_str(), &sizev);
	node = element->FirstChildElement(_TOTAL_PARTICLE_TAG.c_str()); if(node) { tparticle = atoi(node->GetText()); sTparticle = (char*)node->GetText(); }
	node = element->FirstChildElement(_DURATION_TAG.c_str()); if(node) { duration = atof(node->GetText()); sDuration = (char*)node->GetText(); }
	node = element->FirstChildElement(_ANGLE_TAG.c_str()); if(node) { angle = atof(node->GetText()); sAngle = (char*)node->GetText(); }
	node = element->FirstChildElement(_ANGLE_VARIANCE_TAG.c_str()); if(node) { anglev = atof(node->GetText()); sAnglev = (char*)node->GetText(); }
	node = element->FirstChildElement(_RADIAL_ACCEL_TAG.c_str()); if(node) { radacc = atof(node->GetText()); sRadacc = (char*)node->GetText(); }
	node = element->FirstChildElement(_RADIAL_ACCEL_VARIANCE_TAG.c_str()); if(node) { radaccv = atof(node->GetText()); sRadaccv = (char*)node->GetText(); }
	node = element->FirstChildElement(_SPEED_TAG.c_str()); if(node) { speed = atof(node->GetText()); sSpeed = (char*)node->GetText(); }
	node = element->FirstChildElement(_SPEED_VARIANCE_TAG.c_str()); if(node) { speedv = atof(node->GetText()); sSpeedv = (char*)node->GetText(); }
	node = element->FirstChildElement(_LIFE_TAG.c_str()); if(node) { life = atof(node->GetText()); sLife = (char*)node->GetText(); }
	node = element->FirstChildElement(_LIFE_VARIANCE_TAG.c_str()); if(node) { lifev = atof(node->GetText()); sLifev = (char*)node->GetText(); }
	node = element->FirstChildElement(_EMISSION_RATE_TAG.c_str()); if(node) { emissrate = atof(node->GetText()); sEmissrate = (char*)node->GetText(); }
	node = element->FirstChildElement(_SIZE_TAG.c_str()); if(node) { size = atof(node->GetText()); sSize = (char*)node->GetText(); }
	node = element->FirstChildElement(_SIZE_VARIANCE_TAG.c_str()); if(node) { sizev = atof(node->GetText()); sSizev = (char*)node->GetText(); }

	if(sTparticle)
		particle->setTotalParticles((uint32)tparticle);
	if(sDuration)
		particle->setDuration((float)duration);
	if(sAngle)
		particle->setAngle((float)angle);
	if(sAnglev)
		particle->setAngleVariance((float)anglev);
	if(sRadacc)
		particle->setRadialAccel((float)radacc);
	if(sRadaccv)
		particle->setRadialAccelVariance((float)radaccv);
	if(sSpeed)
		particle->setSpeed((float)speed);
	if(sSpeedv)
		particle->setSpeedVariance((float)speedv);
	if(sLife)
		particle->setLife((float)life);
	if(sLifev)
		particle->setLifeVariance((float)lifev);
	if(sEmissrate)
		particle->setEmissionRate((float)emissrate);
	if(sSize)
		particle->setSize((float)size);
	if(sSizev)
		particle->setSizeVariance((float)sizev);

	char* sStartColor = (char*)element->Attribute(_START_COLOLR_TAG.c_str());
	char* sStartColorv = (char*)element->Attribute(_START_COLOR_VARIANCE_TAG.c_str());
	char* sEndColor = (char*)element->Attribute(_END_COLOR_TAG.c_str());
	char* sEndColorv = (char*)element->Attribute(_END_COLOR_VARIANCE_TAG.c_str());
	char* sTexture = (char*)element->Attribute(_TEXTURE_TAG.c_str());
	char* sBlendAdditive = (char*)element->Attribute(_BLEND_ADDITIVE_TAG.c_str());
	char* sColorModulate = (char*)element->Attribute(_COLOR_MODULATE_TAG.c_str());
	node = element->FirstChildElement(_START_COLOLR_TAG.c_str()); if(node) sStartColor = (char*)node->GetText();
	node = element->FirstChildElement(_START_COLOR_VARIANCE_TAG.c_str()); if(node) sStartColorv = (char*)node->GetText();
	node = element->FirstChildElement(_END_COLOR_TAG.c_str()); if(node) sEndColor = (char*)node->GetText();
	node = element->FirstChildElement(_END_COLOR_VARIANCE_TAG.c_str()); if(node) sEndColorv = (char*)node->GetText();
	node = element->FirstChildElement(_TEXTURE_TAG.c_str()); if(node) sTexture = (char*)node->GetText();
	node = element->FirstChildElement(_BLEND_ADDITIVE_TAG.c_str()); if(node) sBlendAdditive = (char*)node->GetText();
	node = element->FirstChildElement(_COLOR_MODULATE_TAG.c_str()); if(node) sColorModulate = (char*)node->GetText();

	if(sStartColor)
	{
		uint32 color32;
		Color color;

		sscanf(sStartColor, "%x", &color32);
		color = Color::fromARGB((float)((color32>>24)&0xFF)/255.f, (float)((color32>>16)&0xFF)/255.f,
			(float)((color32>>8)&0xFF)/255.f, (float)((color32>>0)&0xFF)/255.f);
		particle->setStartColor(color);
	}
	if(sStartColorv)
	{
		uint32 color32;
		Color color;

		sscanf(sStartColorv, "%x", &color32);
		color = Color::fromARGB((float)((color32>>24)&0xFF)/255.f, (float)((color32>>16)&0xFF)/255.f,
			(float)((color32>>8)&0xFF)/255.f, (float)((color32>>0)&0xFF)/255.f);
		particle->setStartColorVariance(color);
	}
	if(sEndColor)
	{
		uint32 color32;
		Color color;

		sscanf(sEndColor, "%x", &color32);
		color = Color::fromARGB((float)((color32>>24)&0xFF)/255.f, (float)((color32>>16)&0xFF)/255.f,
			(float)((color32>>8)&0xFF)/255.f, (float)((color32>>0)&0xFF)/255.f);
		particle->setEndColor(color);
	}
	if(sEndColorv)
	{
		uint32 color32;
		Color color;

		sscanf(sEndColorv, "%x", &color32);
		color = Color::fromARGB((float)((color32>>24)&0xFF)/255.f, (float)((color32>>16)&0xFF)/255.f,
			(float)((color32>>8)&0xFF)/255.f, (float)((color32>>0)&0xFF)/255.f);
		particle->setEndColorVariance(color);
	}

	if(sTexture)
	{
		TCHAR wstr[512]; memset(wstr, 0, sizeof(wstr));
#ifdef UNICODE
		::MultiByteToWideChar(CP_UTF8, 0, sTexture, (int32)strlen(sTexture), wstr, 512);
		Texture* texture = TextureManager::GetInstance().load(wstr);
#else
		Texture* texture = TextureManager::GetInstance().load(sTexture);
#endif
		if(texture)
			particle->setTexture(texture);
	}

	if(sBlendAdditive)
	{
		if(sBlendAdditive == RenderableReader::_TRUE_TAG)
			particle->setBlendAdditive(true);
		else
			particle->setBlendAdditive(false);
	}
	if(sColorModulate)
	{
		if(sColorModulate == RenderableReader::_TRUE_TAG)
			particle->setColorModulate(true);
		else
			particle->setColorModulate(false);
	}

	TiXmlElement* gravity = element->FirstChildElement(_GRAVITY_TAG.c_str());
	if(gravity)
	{
		double x = 0.0, y = 0.0;
		gravity->Attribute(RenderableReader::_X_TAG.c_str(), &x);
		node = gravity->FirstChildElement(RenderableReader::_X_TAG.c_str()); if(node) x = atof(node->GetText());
		gravity->Attribute(RenderableReader::_Y_TAG.c_str(), &y);
		node = gravity->FirstChildElement(RenderableReader::_Y_TAG.c_str()); if(node) y = atof(node->GetText());

		particle->setGravity(Vector2D((float)x, (float)y));
	}

	TiXmlElement* source = element->FirstChildElement(_SOURCE_TAG.c_str());
	if(source)
	{
		double x = 0.0, y = 0.0;
		source->Attribute(RenderableReader::_X_TAG.c_str(), &x);
		node = source->FirstChildElement(RenderableReader::_X_TAG.c_str()); if(node) x = atof(node->GetText());
		source->Attribute(RenderableReader::_Y_TAG.c_str(), &y);
		node = source->FirstChildElement(RenderableReader::_Y_TAG.c_str()); if(node) y = atof(node->GetText());

		particle->setSource(Vector2D((float)x, (float)y));
	}

	TiXmlElement* posv = element->FirstChildElement(_POSITION_VARIANCE_TAG.c_str());
	if(posv)
	{
		double x = 0.0, y = 0.0;
		posv->Attribute(RenderableReader::_X_TAG.c_str(), &x);
		node = posv->FirstChildElement(RenderableReader::_X_TAG.c_str()); if(node) x = atof(node->GetText());
		posv->Attribute(RenderableReader::_Y_TAG.c_str(), &y);
		node = posv->FirstChildElement(RenderableReader::_Y_TAG.c_str()); if(node) y = atof(node->GetText());

		particle->setPositionVariance(Vector2D((float)x, (float)y));
	}

	//parse attachment
	RenderableReader::parseAttachment(element, particle);
	//parse script
	RenderableReader::parseScript(element, particle);

	return particle;
}